package com.thiswhyme.redis.geo;

import com.thiswhyme.redis.geo.entity.GeoMember;
import com.thiswhyme.redis.geo.entity.DistanceMember;
import org.springframework.data.geo.Metrics;

import java.util.List;
import java.util.Map;

/**
 * Geo 模版方法接口
 *
 * @author thiswhyme
 * @date 2022/11/4
 */
public interface GeoTemplate {

    /**
     * 添加元素
     *
     * @param key 集合名
     * @param geoMember 携带经纬度的元素
     * @return 添加的元素个数
     * @param <T> 元素范型
     */
    <T> Long add(String key, GeoMember<T> geoMember);

    /**
     * 批量添加元素
     *
     * @param key 集合名
     * @param geoMembers 携带经纬度的元素列表
     * @return 添加的元素个数
     * @param <T> 元素范型
     */
    <T> Long batchAdd(String key, List<GeoMember<T>> geoMembers);

    /**
     * 删除元素
     *
     * @param key 集合名
     * @param member 元素
     * @return 是否成功删除
     * @param <T> 元素范型
     */
    <T> boolean remove(String key, T member);

    /**
     * 删除元素集
     *
     * @param key 集合名
     * @return 是否成功删除
     */
    boolean clear(String key);

    /**
     * 获取俩元素间距离
     *
     * @param key 集合名
     * @param fromMember  元素A
     * @param toMember 元素B
     * @param metric 距离单位
     * @return 指定单位的距离
     * @param <T> 元素范型
     */
    <T> Double distance(String key, T fromMember, T toMember, Metrics metric);

    /**
     * 获取指定点指定半径内的元素以及对应距离
     *
     * @param key 集合名
     * @param lng 经度
     * @param lat 纬度
     * @param radius 半径
     * @param metric 半径单位
     * @return key：元素，value：距离
     * @param <T> 元素范型
     */
    <T> Map<T, Double> radius(String key, double lng, double lat, double radius, Metrics metric);

    /**
     * 获取指定点指定半径内的元素以及对应距离
     *
     * @param key 集合名
     * @param lng 经度
     * @param lat 纬度
     * @param radius 半径
     * @param metric 半径单位
     * @param count 返回元素个数
     * @return key：元素，value：距离
     * @param <T> 元素范型
     */
    <T> Map<T, Double> radius(String key, double lng, double lat, double radius, Metrics metric, int count);

    /**
     * 获取指定点指定半径内的元素以及对应距离
     *
     * @param key 集合名
     * @param lng 经度
     * @param lat 纬度
     * @param radius 半径
     * @param metric 半径单位
     * @param asc true：按正序查询，false：按逆序查询
     * @return key：元素，value：距离
     * @param <T> 元素范型
     */
    <T> Map<T, Double> radius(String key, double lng, double lat, double radius, Metrics metric, boolean asc);

    /**
     * 获取指定点指定半径内的元素以及对应距离
     *
     * @param key 集合名
     * @param lng 经度
     * @param lat 纬度
     * @param radius 半径
     * @param metric 半径单位
     * @param asc true：按正序查询，false：按逆序查询
     * @param count 返回元素个数
     * @return key：元素，value：距离
     * @param <T> 元素范型
     */
    <T> Map<T, Double> radius(String key, double lng, double lat, double radius, Metrics metric, Boolean asc, Integer count);

    /**
     * 获取指定元素指定半径内的元素以及对应距离
     *
     * @param key 集合名
     * @param member 指定元素
     * @param radius 半径
     * @param metric 半径单位
     * @return key：元素，value：距离
     * @param <T> 元素范型
     */
    <T> Map<T, Double> radius(String key, T member, double radius, Metrics metric);

    /**
     * 获取指定元素指定半径内的元素以及对应距离
     *
     * @param key 集合名
     * @param member 指定元素
     * @param radius 半径
     * @param metric 半径单位
     * @param count 返回元素个数
     * @return key：元素，value：距离
     * @param <T> 元素范型
     */
    <T> Map<T, Double> radius(String key, T member, double radius, Metrics metric, int count);

    /**
     * 获取指定元素指定半径内的元素以及对应距离
     *
     * @param key 集合名
     * @param member 指定元素
     * @param radius 半径
     * @param metric 半径单位
     * @param asc true：按正序查询，false：按逆序查询
     * @return key：元素，value：距离
     * @param <T> 元素范型
     */
    <T> Map<T, Double> radius(String key, T member, double radius, Metrics metric, boolean asc);

    /**
     * 获取指定元素指定半径内的元素以及对应距离
     *
     * @param key 集合名
     * @param member 指定元素
     * @param radius 半径
     * @param metric 半径单位
     * @param asc true：按正序查询，false：按逆序查询
     * @param count 返回元素个数
     * @return key：元素，value：距离
     * @param <T> 元素范型
     */
    <T> Map<T, Double> radius(String key, T member, double radius, Metrics metric, Boolean asc, Integer count);

    /**
     * 将 map 转换为按距离排序的对象
     * @param asc true：正序，false：逆序
     * @return 按距离排序的对象列表
     * @param <T> 元素范型
     */
    <T> List<DistanceMember<T>> mapToSortedObject(Map<T, Double> memberMap, boolean asc);
}

